#include "mainwindow.h"
#include "ui_mainwindow.h"


#include <QTimer>
#include <QTime>
#include <QDebug>
#include <QtGlobal>
#include <QPainter>
#include <QString>
#include <QFont>
#include <stdlib.h>
#include <QMessageBox> //消息盒子
#include <QFile>
#include <QByteArray>



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setWindowTitle("2048游戏");
    this->setFixedSize(660,900);

    ui->pushButton_reset->setFixedSize(200,50);
    ui->pushButton_reset->move(50,180);

    ui->label_score->setFixedSize(150,100);
    ui->label_best->setFixedSize(150,100);
    ui->label_score->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
    ui->label_best->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
    ui->label_score->move(330,60);
    ui->label_best->move(490,60);

     this->r=new Rule( );



    connect(ui->actionBack,&QAction::triggered,[=](){
        //延时触发
        QTimer::singleShot(100,this,[=]{
            emit this->chooseback();  //触发返回上级窗口的信号
        });
    });

    connect(ui->actionRule,&QAction::triggered,[=](){
      //显示游戏规则
        //设置窗口和上级的窗口的位置一致
        this->setGeometry(this->geometry());
        //隐藏当前窗口
         this->hide();
         r->show();


    });

    //点击按钮重置游戏
    connect(ui->pushButton_reset,&QPushButton::clicked,[=](){

        if(this->m_score>this->m_best){  //保存最高的历史记录
            QString str("record.txt");
        QFile file(str);//从文件中获取
       file.open(QIODevice::WriteOnly|QIODevice::Text);//仅写的方式打开文件

        QByteArray array;
        array.setNum(this->m_score);
        file.write(array);
        file.close();
        }
        this->gameInit();
        this->update(); //更新绘图事件

    });

    this->gameInit();



    connect(this->r,&Rule::back,[=](){

        this->setGeometry(this->r->geometry());
        //隐藏当前窗口
         this->show();
         r->hide();
    });

    //添加音效资源
    gameSound=new QSound(":/music.wav",this);

}

MainWindow::~MainWindow()
{
    delete ui;
    delete this->r;
    qDebug()<<"r 已经被释放了";

}
void MainWindow::gameInit()//游戏初始化
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
  //  ppoint xy={60,280};

   //初始化各个矩形的坐标点
     for(int i=0;i<max_i;i++)
         for(int j=0;j<max_j;j++){
             this->m_p[i][j].setX(j*(grid_width)+50);
             this->m_p[i][j].setY(i*(grid_width)+280);
//             qDebug()<<"("<<this->m_p[i][j].x()<<","<<this->m_p[i][j].y()<<")";
            }


   memset(this->m_map,0,sizeof(this->m_map));

    this->m_score=0;
    QFile file("record.txt");//从文件中获取
    file.open(QIODevice::ReadOnly|QIODevice::Text); //仅读的方式打开文件
    QByteArray array=file.readAll();
    file.close();


    this->m_best=array.toInt();

    this->generate_num();
    this->add_color();

}
void  MainWindow::generate_num()//随机生成 2或4
{

    while(1){

        int x=qrand()%max_i;
        int y=qrand()%max_j;
        if(m_map[x][y]==0){
            if(qrand()%10==1){
                m_map[x][y]=4;  //4  十分之一的概率

            }else{

                m_map[x][y]=2;
            }
            break;
        }

    }


}
void MainWindow::add_color(){

    map.insert(0,QColor(204,192,178));
     map.insert(2,QColor(238,228,218));
      map.insert(4,QColor(237,224,200));
       map.insert(8,QColor(204,192,178));
        map.insert(16,QColor(133,155,113));
         map.insert(32,QColor(246,124,95));
          map.insert(64,QColor(245,91,57));
           map.insert(128,QColor(28,151,150));
            map.insert(256,QColor(237,204,97));
             map.insert(512,QColor(255,0,128));
              map.insert(1024,QColor(145,0,128));
               map.insert(2048,QColor(242,17,158));
                map.insert(4096,QColor(200,0,100));
                 map.insert(8192,QColor(242,127,100));
                  map.insert(1,QColor(186,172,159));//背景颜色


}
QColor MainWindow::set_backcolor(int num){


    for(QMap<int,QColor>::iterator it=map.begin(); it!=map.end();it++){

        if(it.key()==num){

            return it.value();
        }

    }


}
void  MainWindow::paintEvent(QPaintEvent *){

       //实例化画家对象
       QPainter  paint(this);
       QPen pen(QColor(112,100,89));
       pen.setWidth(20);
       paint.setPen(pen);
       QFont font;


       //设置2048标题
       font.setPointSize(45);
        paint.setFont(font);

        paint.drawText(QRect(50,100,200,80),Qt::AlignCenter,"2048");

        if(this->m_score<=1000){

            font.setPointSize(30);
        }
        else if(this->m_score<10000&&this->m_score>1000){
             font.setPointSize(25);

        }else if(this->m_score>=10000&this->m_score<100000){

             font.setPointSize(20);
        }else{

            font.setPointSize(15);
        }
        pen.setColor(QColor(240,240,240));

        paint.setPen(pen);
        paint.setFont(font);
        paint.fillRect(QRect(330,90,150,100),QColor(187,173,160));
        paint.fillRect(QRect(490,90,150,100),QColor(187,173,160));
        paint.drawText(QRect(330,100,150,100),Qt::AlignCenter,QString::number(this->m_score));
        paint.drawText(QRect(490,100,150,100),Qt::AlignCenter,QString::number(this->m_best));



       pen.setColor(QColor(212,200,189));
       paint.setPen(pen);
       for(int i=0;i<max_i;i++)
           for(int j=0;j<max_j;j++){


       paint.drawRect(QRect(this->m_p[i][j].x(),this->m_p[i][j].y(),grid_width,grid_width));


           }
       for(int i=0;i<max_i;i++)
           for(int j=0;j<max_j;j++){
               if(m_map[i][j]!=0){

                   QString str=QString::number(m_map[i][j]);
                  // qDebug()<<str;

                   int size;
                   QColor c;
                   if(m_map[i][j]<=512){
                       size=30;
                       if(m_map[i][j]<=4){
                           c.setRgb(178,169,159); //获取数字的颜色
                       }
                       else{

                           c.setRgb(240,240,240);
                       }

                   }else{

                       size=25;
                   }
                   font.setPointSize(size);
                   pen.setColor(c);
                   paint.setPen(pen);
                   paint.setFont(font);
                   //获取数字背景对应的颜色 填充
                   paint.fillRect(QRect(this->m_p[i][j].x()+10,this->m_p[i][j].y()+10,grid_width-20,grid_width-20),this->set_backcolor(m_map[i][j]));

                   paint.drawText(QRect(this->m_p[i][j].x(),this->m_p[i][j].y(),grid_width,grid_width),Qt::AlignCenter,str);
               }

}
}
void MainWindow::keyPressEvent(QKeyEvent *event)//键盘按下事件
{
    if(event->key()==Qt::Key_W|event->key()==Qt::Key_S|event->key()==Qt::Key_A|event->key()==Qt::Key_D){

        this->gameSound->play();

       if(game_over()){ //如果返回值为true 则游戏结束

           if(this->m_score>this->m_best){  //保存最高的历史记录
           QFile file("record.txt");//从文件中获取
           file.open(QIODevice::WriteOnly|QIODevice::Text); //仅写的方式打开文件
           QByteArray array;
           array.setNum(this->m_score);
           file.write(array);
           file.close();
           }

           if( QMessageBox::Save== QMessageBox::information(this,"critical","游戏已结束，是否继续",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
                  {
               this->gameInit();
               this->update(); //更新绘图事件
                 }
                 else{
                     emit this->chooseback();//触发返回主界面的信号
                 }
       }
       else{
       switch(event->key()){
         case Qt::Key_W:
           this->move_up();
           break;
       case Qt::Key_S:
           this->move_down();
           break;
       case Qt::Key_A:
           this->move_left();
           break;
       case Qt::Key_D:
           this->move_right();
           break;


       }

      this->generate_num();//随机生成数字
       this->update();//更新绘图事件
       }
    }





}
//按下键盘的上键
void MainWindow::move_up(){

    int temp; //上移动  以第一行为参照
    for(int j=0;j<max_j;j++){

        temp=0;
        for(int i=1;i<max_i;i++){
            if(m_map[i][j]!=0){  //大前提是本位置数不为0  无意义

            if(m_map[i][j]==m_map[temp][j]){  //与参照位置数相同 合并
                m_map[temp][j]*=2;
                this->m_score+=m_map[temp][j];//更新当前得分
                m_map[i][j]=0;
            }else if(m_map[i][j]!=m_map[temp][j]){ //参照位置数不同

                if(m_map[temp][j]==0){ //特殊 为0

                    m_map[temp][j]=m_map[i][j];
                    m_map[i][j]=0;
                }
                else{
                    if(i-temp>1){
                        m_map[temp+1][j]=m_map[i][j];
                        m_map[i][j]=0;
                    }
                    temp=i;//更新参照
                }

            }
            }
        }

}
}
void MainWindow::move_down(){
    int temp; //下移动  以最后一行为参照
    for(int j=0;j<max_j;j++){

        temp=max_i-1;

        for(int i=max_i-2;i>=0;i--){
            if(m_map[i][j]!=0){  //大前提是本位置数不为0  无意义

            if(m_map[i][j]==m_map[temp][j]){  //与参照位置数相同 合并
                m_map[temp][j]*=2;
                this->m_score+= m_map[temp][j];
                m_map[i][j]=0;
            }else if(m_map[i][j]!=m_map[temp][j]){ //参照位置数不同

                if(m_map[temp][j]==0){ //特殊 为0

                    m_map[temp][j]=m_map[i][j];
                    m_map[i][j]=0;
                }
                else{
                    if(temp-i>1){
                        m_map[temp-1][j]=m_map[i][j];
                        m_map[i][j]=0;
                    }
                    temp=i;//更新参照
                }

            }
            }
        }

}

}
void MainWindow::move_left(){
    int temp; //左移动  以第一列为参照
    for(int i=0;i<max_i;i++){

        temp=0;
        for(int j=1;j<max_j;j++){
            if(m_map[i][j]!=0){  //大前提是本位置数不为0  无意义

            if(m_map[i][j]==m_map[i][temp]){  //与参照位置数相同 合并
                m_map[i][temp]*=2;
                this->m_score+=m_map[i][temp];
                m_map[i][j]=0;
            }else if(m_map[i][j]!=m_map[i][temp]){ //参照位置数不同

                if(m_map[i][temp]==0){ //特殊 为0

                    m_map[i][temp]=m_map[i][j];
                    m_map[i][j]=0;
                }
                else{
                    if(j-temp>1){
                        m_map[i][temp+1]=m_map[i][j];
                        m_map[i][j]=0;
                    }
                    temp=j;//更新参照
                }

            }
            }
        }

}


}
void MainWindow::move_right(){
    int temp; //右移动  以第最后一列为参照
    for(int i=0;i<max_i;i++){

        temp=max_j-1;
        for(int j=max_j-2;j>=0;j--){
            if(m_map[i][j]!=0){  //大前提是本位置数不为0  无意义

            if(m_map[i][j]==m_map[i][temp]){  //与参照位置数相同 合并
                m_map[i][temp]*=2;
                this->m_score+=m_map[i][temp];
                m_map[i][j]=0;
            }else if(m_map[i][j]!=m_map[i][temp]){ //参照位置数不同

                if(m_map[i][temp]==0){ //特殊 为0

                    m_map[i][temp]=m_map[i][j];
                    m_map[i][j]=0;
                }
                else{
                    if(temp-j>1){
                        m_map[i][temp-1]=m_map[i][j];
                        m_map[i][j]=0;
                    }
                    temp=j;//更新参照
                }

            }
            }
        }

}



}
 bool MainWindow::game_over()//判断游戏是否结束
{

        for(int i=0;i<max_i;i++)
            for(int j=0;j<max_j;j++){

                if(m_map[i][j]==0)
                    return false; //如果存在为0的位置 游戏继续
                if(m_map[i][i]==2048){

                 QMessageBox::information(this,"critical","你已经达成2048!!!",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);
                }else if(m_map[i][i]==4096){
                    QMessageBox::information(this,"critical","你已经达成4096，太吊了!!!",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);

                }else if(m_map[i][i]==8192){
                    QMessageBox::information(this,"critical","你已经达成8192,碉堡了",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);

                }
            }
        for(int i=0;i<max_i;i++)
            for(int j=0;j<max_j-1;j++){

                if(m_map[i][j]==m_map[i][j+1])
                    return false;  //如果行存在相邻位置数字相等  游戏继续

            }

        for(int j=0;j<max_j;j++)
            for(int i=0;i<max_i-1;i++){
                if(m_map[i][j]==m_map[i+1][j])//如果存在列相邻位置元素相等  游戏继续
                    return false;

        }
        return true; //游戏结束

 }
